前言

<form> 标签的属性 enctype 设置以何种编码方式提交表单数据。可选的值有三个:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

第一种:这是默认的编码方式。它只处理表单域里的 value 属性值,采用这种编码方式的表单会将表单域的值处理成URL方式。

第二种:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定的文件内容封装到请求参数里。

第三种:这种方式当表单的 action 属性值为 mailto:URL 的形式时比较方便,这种方式主要适用于直接通过表单发送邮件。

前端

<input type="file" name="pic"> 标签用来提交文件。

要注意的是,这个标签的 value 值并不是所选择的文件内容,而是这个文件的完整路径名。

正如前面所说的,表单在提交表单时,如果采用默认编码方式,文件的内容是不会被提交的。 所以表单提交文件内容时要采用 multipart/form-data 编码方式,这需要在服务器端从提交的二进制流中读取文件内容。

后端

中间件的使用方式一般分为两种:

  1. 使用 app.use 的形式
  2. 在路由中作为参数的形式使用

我们使用 express 的中间件 multer 来接收上传的文件,multer 中间件是在路由中作为参数使用的。

  • multer 只会解析 form 设置为 enctype="multipart/form-data" 表单.
  • multer 可以定制存储引擎
  • multer 会将上传的信息以及内容挂载到 request 对象上

具体的使用步骤:

第一 导入 multer 中间件

const multer  = require('multer');

第二 调用 multer

const upload = multer({dest: 'uploads/'}); //不采用这种方式
multer(options) 接受一个 options 对象,其中最基本的是 dest 属性,这将告诉 multer 将上传文件保存在哪。如果你省略 options 对象,这些文件将保存在内存中,永远不会写入磁盘。
dest 的意思是选择一个路径去存储文件,但是这样写有一个小小的问题,存入进来的文件是没有后缀名的。所以我们用下面的配置项

我们一般会使用一个配置项:

const storage = multer.diskStorage({
  // 用来配置文件上传的位置
  destination: (req, file, cb) => {
    // 调用 cb 即可实现上传位置的配置
    cb(null, './public/uploads')
  },
  // 用来配置上传文件的名称(包含后缀)
  filename: (req, file, cb) => {
    //filename 用于确定文件夹中的文件名的确定。 如果没有设置 filename,每个文件将设置为一个随机文件名,并且是没有扩展名的。
    // 获取文件的后缀
    let ext = path.extname(file.originalname)
    // 拼凑文件名
    cb(null, file.fieldname + '-' + Date.now() + ext)
  }
})
const upload = multer({storage: storage})
router.post('/uploader', upload.single('pic'), (req, res) => {
  // upload.single('pic') 意思是告诉 multer 只接收 name 是 pic 的单个文件

  // 将上传成功的文件信息响应给浏览器
  res.json(req.file)
})
重要:这里一定要注意一个路径问题,如果 admin 路由是被引入到 app.js 中使用的,在 destination 中设置路径时,设置的是相对于 app.js 的。

Tips

获取文件扩展名的方式(都是原生)

  • path.parse()
  • path.extname()
path.extname('index.html')
// 返回: '.html'

path.extname('index.coffee.md')
// 返回: '.md'
path.parse('/home/user/dir/file.txt')
// 返回:
// { 
//   root: '/',
//   dir: '/home/user/dir',
//   base: 'file.txt',
//   ext: '.txt',
//   name: 'file' 
// }

布小生
180 声望3 粉丝

如果你追求阳光